1. Problem
You are building a workflow
that must execute business rules based on dynamic information. These
business rules are likely to change over time, and you want to minimize
the impact on the solution when modifications are needed.
2. Solution
This solution will demonstrate
how to call the business rules engine from an orchestration, without
using a .NET assembly. The basic problem is similar to the previous
recipe. The key points of the problem are as follows:
Job applications must be processed, and it must be determined whether applicants meet the minimum age requirement.
If the applicant is younger than a certain age, then that person cannot be considered for employment.
The minimum age is likely to change over time and needs to be easily configurable.
This solution assumes that a
rule exists in the business rules engine to determine whether an
applicant meets the minimum age requirements. To call this rule from an
orchestration, follow these steps:
Open the project containing the orchestration.
In
the orchestration's Properties window, configure it to act as a
long-running transaction by setting the Transaction Type property.
Create a new message, and specify the name and type. In this scenario, create a message named NewHireListMessage defined by the NewHireList schema.
From the toolbox, drag the following onto the design surface in top-down order:
Receive shape to receive the initial order message—configure this shape to use the NewHireListMessage message to activate the orchestration instance and to use an orchestration receive port. Make sure to set the Activate property to True.
Send the shape to deliver the NewHireListMessage message to an external port—configure this shape to use an orchestration send port.
From
the toolbox, drag a Scope shape onto the design surface, in between the
Receive and Send shapes configured in the previous step—configure this
shape to act as an Atomic transaction.
From
the toolbox, drag a Call Rules shape onto the design surface, inside
the Scope shape configured in the previous step. Configure this shape by
double-clicking it, which launches the Call Rules Policy Configuration
dialog box. Select the appropriate business policy to call and the
parameters to pass into the policy (SamplePolicy in this scenario).
NOTE
The Parameter Type
list populates with all the data types expected as input parameters to
the selected business policy. The Parameter Name list populates with all
the orchestration variables and messages matching the parameter types.
3. How It Works
Calling the business
rules engine from an orchestration is a straightforward task. It allows
you to separate the business procedure and process flow from the
business rules. This is particularly useful when the rules are used
across many process flows, change frequently, or need audit logging and
versioning capabilities.
This recipe's solution uses a message instance conforming to the NewHireList schema as an input parameter to the SamplePolicy business rule policy. This policy sets the <Role> element of the message to INVALID APPLICANT if the <Age>
element is less than a certain age. You could then enhance the rule to
apply different minimum age requirements for different roles or to
retrieve real-time minimum age requirements from a government-run data
source.
You could easily extend this
solution to illustrate how the output from a business rule can
facilitate business procedures and process flow within an orchestration.
Business rule policies could define a complex set of rules to determine
whether an applicant is valid for a role. As opposed to setting the <Role>
element to INVALID APPLICANT, you could configure the policy to return a
Boolean value indicating whether the applicant meets the minimum age
requirements. The orchestration could then use this Boolean value in a
Decide shape, allowing separate process flows to determine whether an
applicant is valid for a role based on previous work experience,
personal references, and salary requirements.
For an orchestration to successfully call a policy, you must make a few settings:
The Call Rules shape must be within an Atomic Scope shape (this necessitates that the orchestration's Transaction property is set to Long Running).
The policy must be published and deployed within the business rules engine.
NOTE
The Call Rules shape will always access the most recently deployed version of a policy.
An initialized instance of all variables referenced in the policy must be in the same scope as the Call Rules shape.
Although this solution uses
only an XML message instance as input to the rules policy, policies can
accept other types of input parameters as well. The Vocabulary
Definition Wizard allows a .NET class or class member or a data table or
column to be used as a business term. As previously stated, an
initialized instance of all variables referenced in a policy must be in
scope at the Call Rules shape in the orchestration. This means that if a
.NET class and a data table or column are used in a policy, there must
be an initialized instance of the .NET class and rules engine Microsoft.RuleEngine.DataConnection object available in the orchestration to pass into the policy as input parameters.
NOTE
If there is no
instance matching an input used in a policy's rules, that input
parameter will not appear in the Call Rules Policy Configuration dialog
box's Parameter list. This will prevent the policy from being
successfully called from the orchestration.
The policy used in this scenario references vocabulary definitions based on two XML elements in the NewHireList schema: <Age> and <Role>.
Take care when creating these vocabulary definitions, or the rule
policy won't be able to appropriately handle the orchestration message.
Specifically, set the Document Type
property of the business term to be the fully qualified type name. If
the fully qualified .NET type name is not used to define the BizTalk
schema, BizTalk Server will not have enough information to uniquely
identify the data field.
A finer point regarding the
Call Rules shape is that it treats input parameters as reference
parameters, which means rules may modify the objects passed and return
them to the orchestration. Given that messages are immutable (once they
are created, they cannot be modified) in BizTalk, how does this work?
The answer is that, behind the scenes, the policy creates a modified
copy of the original message. Although this saves the developer's time
when creating their orchestration, it also has an important side effect:
all promoted properties on the original message are removed from the
message context. If properties on the message need to be maintained,
make a copy of the message to allow the message context to be reset
after the business rules engine is called.